//============================================================================
// Name        : object.cpp
// Author      : dfoelber
//============================================================================

#include "object.h"
#include "draw/SDL_draw.h"
#include "graphics/graphics.h"
#include "render_manager.h"
#include "image_manager.h"

/**
* Constructor
* 
* @param image the image the object shows to the player
* @param id the meta ID for the object
* @param owner if the object is the owner of the surface (for cleanup)
* @param autoAdd automatically adds the object to the render manager
**/
Object::Object( Surface* image, int id, bool owner, bool autoAdd )
{
	this->id = id;
	this->image = image;
	this->owner = owner;
	background = NULL;
	
	dirty = hover = false;
	
	path = new Path();
	path->SetSize( image->GetWidth(), image->GetHeight() );
	
	if( autoAdd )
		RenderManager::GetManager()->AddObject(this);
}

/**
* Deconstructor
**/
Object::~Object()
{
	delete path;
	path = NULL;
	
	if (owner)
	{
		delete image;
		image = NULL;
	}
	
	if (background)
	{
		delete background;
		background = NULL;
	}
}

/**
* Returns the object's ID
**/
int Object::GetID()
{
	return id;
}

/**
* Checks if the object is dirty and needs a redraw.
* 
* @return If the object is dirty
**/
bool Object::IsDirty()
{
	return dirty;
}

/**
* Declares the object to be clean.
**/
void Object::SetClean()
{
	dirty = false;
}

/**
* Sets the object's hover state.
* 
* @param hover If the object is being hovered
**/
void Object::SetHover( bool hover )
{
	if( this->hover != hover )
		dirty = true;
	
	this->hover = hover;
}

/**
* Gets the object's hover state.
* 
* @return If the object is being hovered
**/
bool Object::IsHovered()
{
	return hover;
}

/**
* Sets the position of the underlying path. 
* 
* @param x x coordinate
* @param y y coordinate
**/
void Object::SetPosition( int x, int y )
{
	path->SetPosition( x, y );
}

/**
* Sets the object's image.
* 
* @param surface the new surface
* @param owner if the surface transfers ownership
**/
void Object::SetSurface( Surface* surface, bool owner )
{
	if (this->owner)
		delete image;
	
	image = surface;
	path->SetSize( image->GetWidth(), image->GetHeight() );
	
	this->owner = owner;
}

/**
* Accessor to the object's image.
* 
* @return the surface
**/
Surface* Object::GetSurface()
{
	return image;
}

/**
* Sets the object's background.
* 
* @param color the color
* @param alpha the alpha
**/
void Object::SetBackground( Color color, int alpha )
{
	if (image)
	{
		if (background)
			delete background;
		
		background = ImageManager::GetManager()->CreateImage(image->GetWidth(), image->GetHeight());
		
		Draw_FillRect(background->GetSurface(), 0, 0, image->GetWidth(), image->GetHeight(), color.ToUint32());
		
		SDL_SetAlpha(background->GetSurface(), SDL_SRCALPHA, alpha);
	}
}

/**
* Accessor to the object's background (may be NULL).
* 
* @return the background
**/
Surface* Object::GetBackground()
{
	return background;
}

/**
* Sets the object's path. Transfers ownership to the object.
* 
* @param path the new path
**/
void Object::SetPath( Path* path )
{
	if( path != NULL )
	{
		if( this->path != NULL )
			delete this->path;
	
		path->SetSize( image->GetWidth(), image->GetHeight() );
		
		this->path = path;
	}
}

/**
* Accessor to the object's path.
* 
* @return the path
**/	
Path* Object::GetPath()
{
	return path;
}

/**
* Adds another object to this object's association list. Transfers ownership to the object.
* 
* @param object the object to add
*/	
void Object::AddAssociation( Object* object )
{
	for( int i = 0; i < (int)associations.size(); i++ )
	{
		if( object == associations[i] )
			return;
	}
	
	associations.push_back( object );
	object->AddAssociation( this );
	GetPath()->AddAssociation( object->GetPath() );
}

/**
* Removes a specific object to this object's association list.
* 
* @param object the object to remove
**/
void Object::RemoveAssociation( Object* object )
{
	vector<Object*>::iterator iterator;
	for( iterator = associations.begin(); iterator != associations.end(); iterator++ )
	{
		if( object == *iterator )
		{
			associations.erase( iterator );
			object->RemoveAssociation( this );
		}
	}
	
	GetPath()->RemoveAssociation( object->GetPath() );
}

/**
* Removes all objects from this object's association list.
**/
void Object::RemoveAllAssociations()
{
	associations.clear();
	
	GetPath()->RemoveAllAssociations();
}

/**
* Accessor to the object's association list.
* 
* @return the association list
**/	
const vector<Object*>& Object::GetAssociations()
{
	return associations;
}

/**
* Invoked when the object is selected.
**/
void Object::OnSelection()
{	
}
